/*
 *  Copyright 1999-2019 Seata.io Group.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package io.kubesphere.devops.core;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

/**
 * The type Data source proxy.
 *
 * @author sharajava
 */
public class DataSourceProxy extends AbstractDataSourceProxy {

    private static final Logger LOGGER = LoggerFactory.getLogger(DataSourceProxy.class);

    private static final String DEFAULT_RESOURCE_GROUP_ID = "DEFAULT";

    private String partitionName;

    private String partitionIndex;

    private String resourceGroupId;

    private String jdbcUrl;

    private String dbType = "mysql";

    private String userName;

    private void init(DataSource dataSource, String resourceGroupId,String partitionName,String partitionIndex) {
        this.resourceGroupId = resourceGroupId;
        this.targetDataSource = targetDataSource;
        this.partitionName = partitionName;
        this.partitionIndex = partitionIndex;
        try (Connection connection = dataSource.getConnection()) {
            jdbcUrl = connection.getMetaData().getURL();
            dbType = JdbcUtils.getDbType(jdbcUrl);
            userName = connection.getMetaData().getUserName();
        } catch (SQLException e) {
            throw new IllegalStateException("can not init dataSource", e);
        }

    }

    /**
     * Instantiates a new Data source proxy.
     *
     * @param targetDataSource the target data source
     */
    public DataSourceProxy(DataSource targetDataSource, String partitionName,String partitionIndex) {
        this(targetDataSource, DEFAULT_RESOURCE_GROUP_ID, partitionName,partitionIndex);
    }

    /**
     * Instantiates a new Data source proxy.
     *
     * @param targetDataSource the target data source
     * @param resourceGroupId  the resource group id
     */
    public DataSourceProxy(DataSource targetDataSource, String resourceGroupId, String partitionName,String partitionIndex) {
        if (targetDataSource instanceof SeataDataSourceProxy) {
            LOGGER.info("Unwrap the target data source, because the type is: {}", targetDataSource.getClass().getName());
            targetDataSource = ((SeataDataSourceProxy) targetDataSource).getTargetDataSource();
        }
        this.targetDataSource = targetDataSource;
        init(targetDataSource, resourceGroupId,partitionName,partitionIndex);
    }

    /**
     * Gets db type.
     *
     * @return the db type
     */
    public String getDbType() {
        return dbType;
    }

    public String getPartitionName() {
        return partitionName;
    }

    @Override
    public ConnectionProxy getConnection() throws SQLException {
        Connection targetConnection = targetDataSource.getConnection();
        return new ConnectionProxy(this, targetConnection);
    }

    @Override
    public ConnectionProxy getConnection(String username, String password) throws SQLException {
        Connection targetConnection = targetDataSource.getConnection(username, password);
        targetConnection.setAutoCommit(false);
        return new ConnectionProxy(this, targetConnection);
    }

    @Override
    public String getResourceId() {
        return JdbcUtils.buildResourceId(jdbcUrl);
    }

    @Override
    public Connection getPlainConnection() throws SQLException {
        return targetDataSource.getConnection();
    }
}
